/*
 * Copyright (c) 2022, Chongqing UCchip InfoTech Co.,Ltd
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2023-12-22     jlu          the first version
 */
#include "net_prot.h"
#include "config_api.h"
#include "config_boot.h"
#include "config_data.h"
#include "config_factory.h"
#include "factory_api.h"
#include "gateway_manager.h"
#include "json_to_data.h"
#include "module_queue_struct.h"
#include "ota_manager.h"
#include "transparent_protocol.h"
#include "uc_coding.h"
#include "uc_log.h"
#include "wiota_flashing.h"
#include <cJSON.h>
#include <rtthread.h>

/**
 * @brief  解析主题 ID
 *
 * @param  p 输入字符串指针
 * @param  len 输入字符串长度
 * @return 返回主题 ID
 */
int parse_topic_id(const char *p, int len)
{
    int id = 0;
    int i = len - 1;
    int r = 1;
    while (i >= 0 && (unsigned)(p[i] - '0') < 10)
    {
        id += (p[i--] - '0') * r;
        r *= 10;
    }
    return id;
}

/**
 * @brief  解析字符串
 *
 * @param  obj JSON 对象
 * @param  key 键值
 * @return 成功返回字符串，否则返回 NULL
 * @note   字符串需使用 rt_free 释放
 */
static void parse_string_local(char **str, int *len, const cJSON *obj, const char *key)
{
    const cJSON *item = cJSON_GetObjectItemCaseSensitive(obj, key);
    if (cJSON_IsString(item))
    {
        *len = rt_strlen(item->valuestring);
        // 分配内存
        *str = rt_malloc(*len + 1);
        if (RT_NULL == *str)
        {
            TRACE_E("%s, %d malloc failed", __FUNCTION__, __LINE__);
            return;
        }
        // 拷贝字符串
        rt_memcpy(*str, item->valuestring, *len);
        (*str)[*len] = '\0';
    }
    else
        *str = RT_NULL;
}

/**
 * @brief  解析协议头
 *
 * @param  head 协议头
 * @param  obj JSON 对象
 * @return 成功返回0，失败放回非0
 */
static int parse_head(net_head_t *head, const cJSON *root)
{
    signed int i = 0;
    const cJSON *dst = RT_NULL;
    const cJSON *item = RT_NULL;

    parse_uint16(root, "cmd", &head->cmd);
    parse_uint32(root, "src", &head->src_addr);
    dst = cJSON_GetObjectItemCaseSensitive(root, "dst");
    // 目标地址数量
    head->dest_num = cJSON_IsArray(dst) ? cJSON_GetArraySize(dst) : 1;
    // 分配目标地址
    if (head->dest_num > 0)
    {
        head->dest_addr = rt_malloc(head->dest_num * sizeof(unsigned int));
        if (RT_NULL == head->dest_addr)
        {
            TRACE_E("%s, %d malloc failed", __FUNCTION__, __LINE__);
            return -1;
        }
        else
        {
            // 解析单个目标地址
            if (cJSON_IsNumber(dst))
                head->dest_addr[0] = (unsigned int)dst->valuedouble;
            // 解析多个目标地址
            else if (cJSON_IsArray(dst))
            {
                cJSON_ArrayForEach(item, dst)
                {
                    if (cJSON_IsNumber(item))
                        head->dest_addr[i++] = (unsigned int)item->valuedouble;
                }
            }
            else
                head->dest_num = 0;
        }
    }
    else
    {
        head->dest_num = 0;
    }

    return 0;
}

/**
 * @brief  解析 WIoTa 子网配置
 *
 * @param  obj JSON 对象
 * @return WIoTa 子网配置
 */
static wiota_sys_cfg_t *decode_wiota_sys_cfg(const cJSON *obj)
{
    wiota_sys_cfg_t temp_cfg = {0};
    wiota_sys_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(wiota_sys_cfg_t));
    if (0 > parse_wiota_sys_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(wiota_sys_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(wiota_sys_cfg_t));

    return cfg;
}

/**
 * @brief  解析 WIoTa 连接态时间
 *
 * @param  obj JSON 对象
 * @return WIoTa 连接态时间
 */
static wiota_act_cfg_t *decode_wiota_act_cfg(const cJSON *obj)
{
    wiota_act_cfg_t temp_cfg = {0};
    wiota_act_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(wiota_act_cfg_t));
    if (0 > parse_wiota_act_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(wiota_act_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(wiota_act_cfg_t));

    return cfg;
}

/**
 * @brief  解析 WIoTa 频点列表
 *
 * @param  obj JSON 对象
 * @return WIoTa 频点列表
 */
static wiota_freq_cfg_t *decode_wiota_freq_cfg(const cJSON *obj)
{
    wiota_freq_cfg_t temp_cfg = {0};
    wiota_freq_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(wiota_freq_cfg_t));
    if (0 > parse_wiota_freq_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(wiota_freq_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(wiota_freq_cfg_t));

    return cfg;
}

/**
 * @brief  解析 WIoTa 发射功率
 *
 * @param  obj JSON 对象
 * @return WIoTa 发射功率
 */
static wiota_power_cfg_t *decode_wiota_power_cfg(const cJSON *obj)
{
    wiota_power_cfg_t temp_cfg = {0};
    wiota_power_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(wiota_power_cfg_t));
    if (0 > parse_wiota_power_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(wiota_power_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(wiota_power_cfg_t));

    return cfg;
}

/**
 * @brief  解析 WIoTa 速率模式
 *
 * @param  obj JSON 对象
 * @return WIoTa 速率模式
 */
static wiota_rate_cfg_t *decode_wiota_rate_cfg(const cJSON *obj)
{
    wiota_rate_cfg_t temp_cfg = {0};
    wiota_rate_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(wiota_rate_cfg_t));
    if (0 > parse_wiota_rate_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(wiota_rate_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(wiota_rate_cfg_t));

    return cfg;
}

/**
 * @brief  解析 WIoTa 连续信号唤醒并发送数据
 *
 * @param  obj JSON 对象
 * @return WIoTa 连续信号唤醒并发送数据结构体指针
 */
static wiota_paging_tx_and_data_t *decode_wiota_paging_tx_and_data_cfg(const cJSON *obj)
{
    wiota_paging_tx_cfg_t temp_cfg = {0};
    wiota_paging_tx_and_data_t *cfg = RT_NULL;
    char *format = RT_NULL;
    int format_len = 0;

    rt_memset(&temp_cfg, 0xFF, sizeof(wiota_paging_tx_cfg_t));
    // paging字段不可缺省，如果没有，后面也不用解析了
    if (0 > parse_wiota_paging_tx_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(wiota_paging_tx_and_data_t));
    RT_ASSERT(cfg);
    rt_memset(cfg, 0, sizeof(wiota_paging_tx_and_data_t));

    // paging tx配置
    cfg->paging_tx = rt_malloc(sizeof(wiota_paging_tx_cfg_t));
    RT_ASSERT(cfg->paging_tx);
    rt_memcpy(cfg->paging_tx, &temp_cfg, sizeof(wiota_paging_tx_cfg_t));

    // 解析是否有data字段，有数据则表示唤醒并发送数据，没有数据则只唤醒
    const cJSON *user_data_obj = cJSON_GetObjectItemCaseSensitive(obj, "data");
    if (user_data_obj)
    {
        cfg->user_data = rt_malloc(sizeof(net_dl_userdata_t));
        RT_ASSERT(cfg->user_data);
        rt_memset(cfg->user_data, 0, sizeof(net_dl_userdata_t));

        // 协议头在obj
        parse_head(&cfg->user_data->head, obj);
        cfg->user_data->head.cmd = PROT_USER_DATA; // 该命令协议头cmd为2，但是携带数据发送只能是单播，强制转化为100
        // delay fmt uc bc在user_data_obj
        parse_uint32(user_data_obj, "delay", &cfg->user_data->send_delay);
        parse_string_local(&format, &format_len, user_data_obj, "fmt");
        rt_memcpy(cfg->user_data->fmt, format, format_len);
        parse_string_local(&cfg->user_data->unicast_data, &cfg->user_data->unicast_len, user_data_obj, "uc");
        parse_string_local(&cfg->user_data->broadcast_data, &cfg->user_data->broadcast_len, user_data_obj, "bc");

        rt_free(format);
    }

    return cfg;
}

/**
 * @brief  解析 WIoTa 周期信号唤醒配置
 *
 * @param  obj JSON 对象
 * @return WIoTa 周期信号唤醒配置
 */
static wiota_sync_paging_cfg_t *decode_wiota_sync_paging_cfg(const cJSON *obj)
{
    wiota_sync_paging_cfg_t temp_cfg = {0};
    wiota_sync_paging_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(wiota_sync_paging_cfg_t));
    if (0 > parse_wiota_sync_paging_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(wiota_sync_paging_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(wiota_sync_paging_cfg_t));

    return cfg;
}

/**
 * @brief  解析WIoTa授时配置
 *
 * @param  obj JSON 对象
 * @return AP 授时配置
 */
static wiota_ts_cfg_t *decode_wiota_ts_cfg(const cJSON *obj)
{
    wiota_ts_cfg_t temp_cfg = {0};
    wiota_ts_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(wiota_ts_cfg_t));
    if (0 > parse_wiota_ts_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(wiota_ts_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(wiota_ts_cfg_t));

    return cfg;
}

#ifdef WIOTA_SUBF_MODE_SUPPORT
/**
 * @brief  解析WIoTa子帧模式配置
 *
 * @param  obj JSON 对象
 * @return AP 授时配置
 */
static wiota_subf_mode_cfg_t *decode_wiota_subf_mode_cfg(const cJSON *obj)
{
    wiota_subf_mode_cfg_t temp_cfg = {0};
    wiota_subf_mode_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(wiota_subf_mode_cfg_t));
    if (0 > parse_wiota_subf_mode_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(wiota_subf_mode_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(wiota_subf_mode_cfg_t));

    return cfg;
}
#endif

/**
 * @brief  解析分时发送
 *
 * @param  obj JSON 对象
 * @return 分时发送
 */
static slot_send_cfg_t *decode_slot_send_cfg(const cJSON *obj)
{
    slot_send_cfg_t temp_cfg = {0};
    slot_send_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(slot_send_cfg_t));
    if (0 > parse_slot_send_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(slot_send_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(slot_send_cfg_t));

    return cfg;
}

/**
 * @brief  解析uboot配置
 *
 * @param  obj JSON 对象
 * @return uboot配置
 */
static uboot_cfg_t *decode_uboot_cfg(const cJSON *obj)
{
    uboot_cfg_t temp_cfg = {0};
    uboot_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(uboot_cfg_t));
    if (0 > parse_uboot_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(uboot_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(uboot_cfg_t));

    return cfg;
}

/**
 * @brief  解析立即生效配置
 *
 * @param  obj JSON 对象
 * @return 立即生效配置
 */
static unsigned int *decode_immediate_effective_cfg(const cJSON *obj)
{
    unsigned int *cfg = RT_NULL;
    unsigned int flag = 0xFFFFFFFF;

    if (0 != parse_uint32(obj, IMMEDIATE_EFFECTIVE_CFG, &flag))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(int));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &flag, sizeof(int));

    return cfg;
}

/**
 * @brief  解析同步助手配置
 *
 * @param  obj JSON 对象
 * @return 同步助手配置
 */
static sync_cfg_t *decode_sync_cfg(const cJSON *obj)
{
    sync_cfg_t temp_cfg = {0};
    sync_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(sync_cfg_t));
    if (0 > parse_sync_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(sync_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(sync_cfg_t));

    return cfg;
}

/**
 * @brief  解析网关基础配置
 *
 * @param  obj JSON 对象
 * @return 网关基础配置
 */
static gw_base_cfg_t *decode_gateway_base_cfg(const cJSON *obj)
{
    gw_base_cfg_t temp_cfg = {0};
    gw_base_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(gw_base_cfg_t));
    if (0 > parse_gateway_base_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(gw_base_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(gw_base_cfg_t));

    return cfg;
}

/**
 * @brief  解析分配地址
 *
 * @param  obj JSON 对象
 * @return 分配地址
 */
static gw_id_manager_cfg_t *decode_gateway_id_mng_cfg(const cJSON *obj)
{
    gw_id_manager_cfg_t temp_cfg = {0};
    gw_id_manager_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(gw_id_manager_cfg_t));
    if (0 > parse_gateway_id_mng_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(gw_id_manager_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(gw_id_manager_cfg_t));

    return cfg;
}

/**
 * @brief  解析鉴权信息
 *
 * @param  obj JSON 对象
 * @return 鉴权信息
 */
static gw_auth_cfg_t *decode_gateway_auth_cfg(const cJSON *obj)
{
    gw_auth_cfg_t temp_cfg = {0};
    gw_auth_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(gw_auth_cfg_t));
    if (0 > parse_gateway_auth_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(gw_auth_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(gw_auth_cfg_t));

    return cfg;
}

/**
 * @brief  解析网卡策略配置
 *
 * @param  obj JSON 对象
 * @return 网卡策略配置
 */
static gw_net_policy_cfg_t *decode_gateway_net_policy_cfg(const cJSON *obj)
{
    gw_net_policy_cfg_t temp_cfg = {0};
    gw_net_policy_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(gw_net_policy_cfg_t));
    if (0 > parse_gateway_net_policy_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(gw_net_policy_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(gw_net_policy_cfg_t));

    return cfg;
}

/**
 * @brief  解析网口配置
 *
 * @param  obj JSON 对象
 * @return 网口配置
 */
static gw_net_if_cfg_t *decode_gateway_net_if_cfg(const cJSON *obj)
{
    gw_net_if_cfg_t temp_cfg = {0};
    gw_net_if_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(gw_net_if_cfg_t));
    if (0 > parse_gateway_net_if_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(gw_net_if_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(gw_net_if_cfg_t));

    return cfg;
}

/**
 * @brief  解析WIFI配置
 *
 * @param  obj JSON 对象
 * @return WIFI配置
 */
static gw_wifi_cfg_t *decode_gateway_wifi_cfg(const cJSON *obj)
{
    gw_wifi_cfg_t temp_cfg = {0};
    gw_wifi_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(gw_wifi_cfg_t));
    if (0 > parse_gateway_wifi_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(gw_wifi_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(gw_wifi_cfg_t));

    return cfg;
}

/**
 * @brief  解析CAT1配置
 *
 * @param  obj JSON 对象
 * @return CAT1配置
 */
static gw_cat1_cfg_t *decode_gateway_cat1_cfg(const cJSON *obj)
{
    gw_cat1_cfg_t temp_cfg = {0};
    gw_cat1_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(gw_cat1_cfg_t));
    if (0 > parse_gateway_cat1_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(gw_cat1_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(gw_cat1_cfg_t));

    return cfg;
}

/**
 * @brief  解析 MQTT 服务器
 *
 * @param  obj JSON 对象
 * @return MQTT服务器
 */
static gw_mqtt_server_cfg_t *decode_gateway_mqtt_cfg(const cJSON *obj)
{
    gw_mqtt_server_cfg_t temp_cfg = {0};
    gw_mqtt_server_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(gw_mqtt_server_cfg_t));
    if (0 > parse_gateway_mqtt_server_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(gw_mqtt_server_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(gw_mqtt_server_cfg_t));

    return cfg;
}

/**
 * @brief  解析上下行数据配置
 *
 * @param  obj JSON 对象
 * @return 上下行数据解码配置
 */
static gw_data_cfg_t *decode_gateway_data_cfg(const cJSON *obj)
{
    gw_data_cfg_t temp_cfg = {0};
    gw_data_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(gw_data_cfg_t));
    if (0 > parse_gateway_data_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(gw_data_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(gw_data_cfg_t));

    return cfg;
}

/**
 * @brief  解析看门狗
 *
 * @param  obj JSON 对象
 * @return 看门狗
 */
static gw_wtd_cfg_t *decode_gateway_wtd_cfg(const cJSON *obj)
{
    gw_wtd_cfg_t temp_cfg = {0};
    gw_wtd_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(gw_wtd_cfg_t));
    if (0 > parse_gateway_wtd_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(gw_wtd_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(gw_wtd_cfg_t));

    return cfg;
}

/**
 * @brief  解析网关log配置
 *
 * @param  obj JSON 对象
 * @return 网关log配置
 */
static gw_ftp_log_cfg_t *decode_gateway_log_cfg(const cJSON *obj)
{
    gw_ftp_log_cfg_t temp_cfg = {0};
    gw_ftp_log_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(gw_ftp_log_cfg_t));
    if (0 > parse_gateway_ftp_log_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(gw_ftp_log_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(gw_ftp_log_cfg_t));

    return cfg;
}

/**
 * @brief  解析网关log口切换配置
 *
 * @param  obj JSON 对象
 * @return 网关log切换配置
 */
static gw_log_switch_cfg_t *decode_gateway_log_switch_cfg(const cJSON *obj)
{
    gw_log_switch_cfg_t temp_cfg = {0};
    gw_log_switch_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(gw_log_switch_cfg_t));
    if (0 > parse_gateway_log_switch_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(gw_log_switch_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(gw_log_switch_cfg_t));

    return cfg;
}

/**
 * @brief  解析网关uart_485配置
 *
 * @param  obj JSON 对象
 * @return 网关uart_485配置
 */
static gw_uart_485_cfg_t *decode_gateway_uart_485_cfg(const cJSON *obj)
{
    gw_uart_485_cfg_t temp_cfg = {0};
    gw_uart_485_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(gw_uart_485_cfg_t));
    if (0 > parse_gateway_uart_485_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(gw_uart_485_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(gw_uart_485_cfg_t));

    return cfg;
}

/**
 * @brief  解析网关定时配置
 *
 * @param  obj JSON 对象
 * @return 网关定时配置
 */
static gw_timed_cfg_t *decode_gateway_timed_cfg(const cJSON *obj)
{
    gw_timed_cfg_t temp_cfg = {0};
    gw_timed_cfg_t *cfg = RT_NULL;

    rt_memset(&temp_cfg, 0xFF, sizeof(gw_timed_cfg_t));
    if (0 > parse_gateway_timed_cfg(obj, &temp_cfg))
    {
        return RT_NULL;
    }

    cfg = rt_malloc(sizeof(gw_timed_cfg_t));
    RT_ASSERT(cfg);

    rt_memcpy(cfg, &temp_cfg, sizeof(gw_timed_cfg_t));

    return cfg;
}

/**
 * @brief  解析升级信息
 *
 * @param  obj JSON 对象
 * @param  key 键值
 * @return 升级信息
 */
void *parse_ota_update(const cJSON *obj)
{
    ota_upgrade_req_t *cfg = RT_NULL;
    const cJSON *item = cJSON_GetObjectItemCaseSensitive(obj, "ota");
    if (cJSON_IsObject(item))
    {
        // 分配内存
        cfg = rt_malloc(sizeof(ota_upgrade_req_t));
        if (RT_NULL == cfg)
        {
            TRACE_E("%s, %d malloc failed", __FUNCTION__, __LINE__);
        }
        else
        {
            rt_memset(cfg, 0xFF, sizeof(ota_upgrade_req_t));
            // 解析升级信息
            parse_uint32(item, "active", &cfg->active_state);

            parse_uint32(item, "type", &cfg->ota_info.upgrade_type);
            parse_uint32(item, "range", &cfg->ota_info.upgrade_range);
            parse_uint32_array(item, "iote", cfg->ota_info.iote_list, 8);
            parse_string(item, "new_ver", cfg->ota_info.new_version, 16);
            parse_string(item, "old_ver", cfg->ota_info.old_version, 16);
            parse_string(item, "dev_type", cfg->ota_info.device_type, 12);
            parse_string(item, "md5", cfg->ota_info.md5, 36);

            const cJSON *net = cJSON_GetObjectItemCaseSensitive(item, "net");
            if (cJSON_IsObject(net))
            {
                parse_uint32(net, "access", &cfg->http_info.access);
                parse_string(net, "file", cfg->http_info.file_name, 32);
                parse_string(net, "usr", cfg->http_info.username, 32);
                parse_string(net, "pwd", cfg->http_info.password, 32);
                parse_string(net, "path", cfg->http_info.path, 64);
                parse_string(net, "addr", cfg->http_info.address, 128);
                parse_uint32(net, "port", &cfg->http_info.port);
            }
        }
    }
    return cfg;
}

/**
 * @brief  解析设置配置
 *
 * @param  obj JSON 对象
 * @return 配置
 */
void *parse_set_config(const cJSON *obj)
{
    net_cfg_set_t *param = RT_NULL;
    // 分配内存
    param = rt_malloc(sizeof(net_cfg_set_t));
    if (RT_NULL == param)
    {
        TRACE_E("%s, %d malloc failed", __FUNCTION__, __LINE__);
        return RT_NULL;
    }
    rt_memset(param, 0, sizeof(net_cfg_set_t));
    // 解析 WIoTa 配置
    param->sys_cfg = decode_wiota_sys_cfg(obj);
    // 解析 WIoTa 连接态时间
    param->act_cfg = decode_wiota_act_cfg(obj);
    // 解析 WIoTa 频点列表
    param->freq_cfg = decode_wiota_freq_cfg(obj);
    // 解析 WIoTa 发射功率
    param->power_cfg = decode_wiota_power_cfg(obj);
    // 解析 WIoTa 速率模式
    param->rate_cfg = decode_wiota_rate_cfg(obj);
    // 解析 WIoTa 连续信号唤醒配置
    param->paging_tx_cfg = decode_wiota_paging_tx_and_data_cfg(obj);
    // 解析 WIoTa 周期信号唤醒配置
    param->sync_paging_cfg = decode_wiota_sync_paging_cfg(obj);
    // 解析 WIoTa 授时配置
    param->ts_cfg = decode_wiota_ts_cfg(obj);
#ifdef WIOTA_SUBF_MODE_SUPPORT
    // 解析 WIoTa 子帧模式配置
    param->subf_cfg = decode_wiota_subf_mode_cfg(obj);
#endif
    // 解析网关配置
    param->base_cfg = decode_gateway_base_cfg(obj);
    // 解析鉴权信息
    param->auth_cfg = decode_gateway_auth_cfg(obj);
    // 解析分配地址
    param->id_mng_cfg = decode_gateway_id_mng_cfg(obj);
    // 解析网络配置
    param->net_policy_cfg = decode_gateway_net_policy_cfg(obj);
    // 解析网卡配置
    param->net_if_cfg = decode_gateway_net_if_cfg(obj);
    // 解析WIFI配置
    param->wifi_cfg = decode_gateway_wifi_cfg(obj);
    // 解析CAT1配置
    param->cat1_cfg = decode_gateway_cat1_cfg(obj);
    // 解析MQTT服务器
    param->mqtt_server_cfg = decode_gateway_mqtt_cfg(obj);
    // 解析上下行数据配置
    param->data_cfg = decode_gateway_data_cfg(obj);
    // 解析看门狗
    param->wtd_cfg = decode_gateway_wtd_cfg(obj);
    // 解析网关LOG
    param->log_cfg = decode_gateway_log_cfg(obj);
    // 解析网关LOG切换配置
    param->log_switch_cfg = decode_gateway_log_switch_cfg(obj);
    // 解析网关uart_485配置
    param->uart_485_cfg = decode_gateway_uart_485_cfg(obj);
    // 解析网关定时配置
    param->timed_cfg = decode_gateway_timed_cfg(obj);
    // 解析分时发送
    param->slot_send_cfg = decode_slot_send_cfg(obj);
    // 解析Ymodem等待时间
    param->uboot_cfg = decode_uboot_cfg(obj);
    // 解析立即生效配置
    param->immediate_effective_cfg = decode_immediate_effective_cfg(obj);
    // 解析同步助手配置
    param->sync_cfg = decode_sync_cfg(obj);

    return param;
}

/**
 * @brief  解析查询配置
 *
 * @param  obj JSON 对象
 * @return 配置命令
 */
int parse_query_config(const cJSON *obj)
{
    net_cfg_query_t param = {0};
    int cmd = 0;

    parse_string(obj, "query", param.query, sizeof(param.query));

    if (0 == rt_strcmp(param.query, WIOTA_VERSION))
        cmd = WIOAT_VERSION_GET;
    else if (0 == rt_strcmp(param.query, WIOTA_SYS_CFG))
        cmd = WIOTA_SYS_CFG_GET;
    else if (0 == rt_strcmp(param.query, WIOTA_ACT_CFG))
        cmd = WIOTA_ACT_CFG_GET;
    else if (0 == rt_strcmp(param.query, WIOTA_FREQ_CFG))
        cmd = WIOTA_FREQ_CFG_GET;
    else if (0 == rt_strcmp(param.query, WIOTA_POWER_CFG))
        cmd = WIOTA_POWER_CFG_GET;
    else if (0 == rt_strcmp(param.query, WIOTA_RATE_CFG))
        cmd = WIOTA_RATE_CFG_GET;
    else if (0 == rt_strcmp(param.query, WIOTA_PAGING_TX_CFG))
        cmd = WIOTA_PAGING_TX_CFG_GET;
    else if (0 == rt_strcmp(param.query, WIOTA_SYNC_PAGING_CFG))
        cmd = WIOTA_SYNC_PAGING_CFG_GET;
    else if (0 == rt_strcmp(param.query, WIOTA_TS_CFG))
        cmd = WIOTA_TS_CFG_GET;
#ifdef WIOTA_SUBF_MODE_SUPPORT
    else if (0 == rt_strcmp(param.query, WIOTA_SUBF_MODE_CFG, rt_strlen(WIOTA_SUBF_MODE_CFG)))
        cmd = WIOTA_SUBF_MODE_CFG_GET;
#endif
    else if (0 == rt_strcmp(param.query, GW_BASE_CFG))
        cmd = GATEWAY_BASE_CFG_GET;
    else if (0 == rt_strcmp(param.query, GW_ID_MNG_CFG))
        cmd = ID_MANAGER_CFG_GET;
    else if (0 == rt_strcmp(param.query, GW_AUTH_CFG))
        cmd = AUTH_CFG_GET;
    else if (0 == rt_strcmp(param.query, GW_NET_CFG))
        cmd = NET_CFG_GET;
    else if (0 == rt_strcmp(param.query, NETDEV_POLICY))
        cmd = NET_POLICY_CFG_GET;
    else if (0 == rt_strcmp(param.query, NET_INTERFACE))
        cmd = NET_IF_CFG_GET;
    else if (0 == rt_strcmp(param.query, GW_WIFI_CFG))
        cmd = WIFI_CFG_GET;
    else if (0 == rt_strcmp(param.query, GW_CAT1_CFG))
        cmd = CAT1_CFG_GET;
    else if (0 == rt_strcmp(param.query, GW_BT_CFG))
        cmd = BT_CFG_GET;
    else if (0 == rt_strcmp(param.query, GW_MQTT_CFG))
        cmd = MQTT_SERVER_CFG_GET;
    else if (0 == rt_strcmp(param.query, GW_DATA_CFG))
        cmd = DATA_CFG_GET;
    else if (0 == rt_strcmp(param.query, GW_WTD_CFG))
        cmd = WATCHDOG_CFG_GET;
    else if (0 == rt_strcmp(param.query, FTP_LOG))
        cmd = GATEWAY_FTP_LOG_CFG_GET;
    else if (0 == rt_strcmp(param.query, GW_LOG_SWITCH_CFG))
        cmd = LOG_SWITCH_CFG_GET;
    else if (0 == rt_strcmp(param.query, GW_UART_485_CFG))
        cmd = UART_485_CFG_GET;
    else if (0 == rt_strcmp(param.query, SLOT_SEND_CFG))
        cmd = SLOT_SEND_CFG_GET;
    else if (0 == rt_strcmp(param.query, GW_RESET_FACTORY))
        cmd = RESET_FACTORY;
    else if (0 == rt_strcmp(param.query, GW_REBOOT))
        cmd = GATEWAY_REBOOT;
    else if (0 == rt_strcmp(param.query, GW_ALL_CFG))
        cmd = ALL_CFG_GET;
    else if (0 == rt_strcmp(param.query, UBOOT_CFG))
        cmd = UBOOT_CFG_GET;
    else if (0 == rt_strcmp(param.query, IMMEDIATE_EFFECTIVE_CFG))
        cmd = IMMEDIATE_EFFECTIVE_GET;
    else if (0 == rt_strcmp(param.query, FACTORY_TEST_RESULT))
        cmd = FACTORY_TEST_RESULT_GET;
    else if (0 == rt_strcmp(param.query, GW_TIMED_CFG))
        cmd = GATEWAY_TIMED_CFG_GET;
    else if (0 == rt_strcmp(param.query, SYNC_ASSISTANT_CFG))
        cmd = SYNC_CFG_GET;
    else if (0 == rt_strcmp(param.query, GW_AUTH_LIST))
        cmd = GATEWAY_AUTH_LIST_GET;
    else if (0 == rt_strcmp(param.query, SYNC_DYNAMICS_INFO))
        cmd = SYNC_DYNAMICS_INFO_GET;

    return cmd;
}

/**
 * @brief  解析执行配置
 *
 * @param  obj JSON 对象
 * @return 配置命令
 */
int parse_exec_config(const cJSON *obj)
{
    net_cfg_exec_t param = {0};
    int cmd = 0;

    parse_string(obj, "exec", param.exec, sizeof(param.exec));

    if (0 == rt_strcmp(param.exec, GW_RESET_FACTORY))
        cmd = RESET_FACTORY;
    else if (0 == rt_strcmp(param.exec, GW_REBOOT))
        cmd = GATEWAY_REBOOT;
    else if (0 == rt_strcmp(param.exec, GW_SCAN_FREQ_STOP))
        cmd = GATEWAY_SCAN_FREQ_STOP;

    return cmd;
}

/**
 * @brief  解析用户数据
 *
 * @param  root JSON 对象
 * @return 成功返回用户数据指针，否则返回 NULL
 */
void *parse_user_data(const cJSON *root)
{
    char *format = RT_NULL;
    int format_len = 0;

    net_dl_userdata_t *user_data = RT_NULL;
    // 分配内存
    user_data = rt_malloc(sizeof(net_dl_userdata_t));
    if (RT_NULL == user_data)
    {
        TRACE_E("%s, %d malloc failed", __FUNCTION__, __LINE__);
        return RT_NULL;
    }
    rt_memset(user_data, 0, sizeof(net_dl_userdata_t));

    // 解析协议头
    parse_head(&user_data->head, root);
    // 解析用户数据
    parse_string_local(&format, &format_len, root, "fmt");
    rt_memcpy(user_data->fmt, format, format_len);
    parse_uint32(root, "ob", &user_data->order_business);
    parse_string_local(&user_data->unicast_data, &user_data->unicast_len, root, "uc");
    parse_string_local(&user_data->broadcast_data, &user_data->broadcast_len, root, "bc");

    // 释放内存
    rt_free(format);
    format = RT_NULL;
    return user_data;
}

/**
 * @brief  解析透传数据
 *
 * @param  root JSON 对象
 * @return 成功返回用户数据指针，否则返回 NULL
 */
void *parse_transparent_data(const cJSON *root)
{
    char *format = RT_NULL;
    int format_len = 0;

    net_dl_transparent_data_t *transparent_data = RT_NULL;
    // 分配内存
    transparent_data = rt_malloc(sizeof(net_dl_transparent_data_t));
    if (RT_NULL == transparent_data)
    {
        TRACE_E("%s, %d malloc failed", __FUNCTION__, __LINE__);
        return RT_NULL;
    }
    rt_memset(transparent_data, 0, sizeof(net_dl_transparent_data_t));

    // 解析协议头
    parse_uint16(root, "cmd", &transparent_data->cmd);
    parse_uint32(root, "src", &transparent_data->src_addr);
    parse_uint32(root, "dst", &transparent_data->dest_addr);
    // 解析用户数据
    parse_string_local(&format, &format_len, root, "fmt");
    rt_memcpy(transparent_data->fmt, format, format_len);
    parse_string_local(&transparent_data->transparent_data, &transparent_data->transparent_data_len, root, "data");

    // 释放内存
    rt_free(format);
    format = RT_NULL;
    return transparent_data;
}

/**
 * @brief  解析扫描频点请求
 *
 * @param root   JSON 对象
 * @return void* 成功返回扫描频点请求指针，否则返回 RT_NULL
 */
void *parse_scan_freq_request(const cJSON *root)
{
    const cJSON *scan_freq_ojb = cJSON_GetObjectItemCaseSensitive(root, "scan_freq");
    const cJSON *item = RT_NULL;
    const cJSON *freq_list_obj = RT_NULL;
    int i = 0;

    if (cJSON_IsObject(scan_freq_ojb))
    {
        gw_scan_freq_req_t *scan_freq_req = rt_malloc(sizeof(gw_scan_freq_req_t));
        if (RT_NULL == scan_freq_req)
        {
            TRACE_E("%s, %d malloc failed", __FUNCTION__, __LINE__);
            return RT_NULL;
        }
        rt_memset(scan_freq_req, 0, sizeof(gw_scan_freq_req_t));

        parse_uint32(scan_freq_ojb, "times", &scan_freq_req->scan_times);
        parse_uint32(scan_freq_ojb, "freq_num", &scan_freq_req->freq_num);

        // 只要收到该命令，至少扫一次
        if (scan_freq_req->scan_times == 0)
        {
            scan_freq_req->scan_times = 1;
        }
        // scan_freq_req->freq_num为0表示扫网关频点列表，为201表示全扫，不在解析freq_list
        if (scan_freq_req->freq_num > 0 && scan_freq_req->freq_num != 201)
        {
            scan_freq_req->freq_list = rt_malloc(sizeof(unsigned char) * scan_freq_req->freq_num);
            if (RT_NULL == scan_freq_req->freq_list)
            {
                TRACE_E("%s, %d malloc failed", __FUNCTION__, __LINE__);
                rt_free(scan_freq_req);
                return RT_NULL;
            }
            rt_memset(scan_freq_req->freq_list, 0, sizeof(unsigned char) * scan_freq_req->freq_num);

            freq_list_obj = cJSON_GetObjectItemCaseSensitive(scan_freq_ojb, "freq_list");
            if (cJSON_IsNumber(freq_list_obj))
            {
                scan_freq_req->freq_list[0] = (unsigned char)freq_list_obj->valuedouble;
                i = 1;
            }
            else if (cJSON_IsArray(freq_list_obj))
            {
                cJSON_ArrayForEach(item, freq_list_obj)
                {
                    if (cJSON_IsNumber(item))
                    {
                        if (i < scan_freq_req->freq_num)
                        {
                            scan_freq_req->freq_list[i++] = (unsigned char)item->valuedouble;
                        }
                    }
                }
            }
            else
            {
                i = 0;
                rt_free(scan_freq_req->freq_list);
                scan_freq_req->freq_list = RT_NULL;
            }

            if (i != scan_freq_req->freq_num)
            {
                TRACE_E("freq_num not match, actual_freq_num %d, freq_num %d", i, scan_freq_req->freq_num);
                scan_freq_req->freq_num = i;
            }
        }

        return scan_freq_req;
    }

    return RT_NULL;
}

/**
 * @brief  编码 head 信息
 *
 * @param  root 根节点
 * @param  head 头信息
 */
static void encode_head(cJSON *root, const net_head_t *head)
{
    if (RT_NULL != head)
    {
        cJSON_AddNumberToObject(root, "cmd", head->cmd);
        cJSON_AddStringToObject(root, "ver", PROT_VERSION);
        cJSON_AddNumberToObject(root, "src", head->src_addr);
        // 如果只有一个目标地址
        if (head->dest_num == 1)
        {
            cJSON_AddNumberToObject(root, "dst", head->dest_addr[0]);
        }
        // 如果有多个目标地址
        else if (head->dest_num > 1)
        {
            cJSON *dst = cJSON_CreateArray();
            if (RT_NULL != dst)
            {
                // 循环添加目标地址
                for (unsigned short i = 0; i < head->dest_num; ++i)
                {
                    cJSON_AddItemToArray(dst, cJSON_CreateNumber(head->dest_addr[i]));
                }
                cJSON_AddItemToObject(root, "dst", dst);
            }
        }
    }
}

/**
 * @brief  编码网关所有配置信息
 *
 * @return char* 成功返回编码结果，否则返回 RT_NULL
 */
char *encode_gateway_all_cfg(void)
{
    char *payload = RT_NULL;
    net_head_t head = {0};
    gateway_cfg_t temp_gw_cfg = {0};
    gateway_cfg_t *gw_cfg = uc_static_get_gateway_cfg();
    static unsigned char get_cfg_cnt = 0;
    unsigned char is_have_data = RT_TRUE;

    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root)
    {
        head.cmd = PROT_QUERY_CONFIG;
        encode_head(root, &head);

        switch (get_cfg_cnt)
        {
        case 0:
            add_uboot_cfg(root, uc_get_uboot_cfg());
            break;
        case 1:
            add_wiota_cfg(root, uc_static_get_wiota_cfg());
            break;
        case 2:
            // 密码不可见
            rt_memcpy(&temp_gw_cfg, gw_cfg, sizeof(gateway_cfg_t));
            if (rt_strlen(temp_gw_cfg.wifi_cfg.password) > 0)
            {
                rt_memset(temp_gw_cfg.wifi_cfg.password, 0, sizeof(temp_gw_cfg.wifi_cfg.password));
                rt_memset(temp_gw_cfg.wifi_cfg.password, '*', PASSWORD_DISPLAY_LEN);
            }
            if (rt_strlen(temp_gw_cfg.mqtt_server_cfg.password) > 0)
            {
                rt_memset(temp_gw_cfg.mqtt_server_cfg.password, 0, sizeof(temp_gw_cfg.mqtt_server_cfg.password));
                rt_memset(temp_gw_cfg.mqtt_server_cfg.password, '*', PASSWORD_DISPLAY_LEN);
            }
            if (rt_strlen(temp_gw_cfg.log_cfg.password) > 0)
            {
                rt_memset(temp_gw_cfg.log_cfg.password, 0, sizeof(temp_gw_cfg.log_cfg.password));
                rt_memset(temp_gw_cfg.log_cfg.password, '*', PASSWORD_DISPLAY_LEN);
            }
            add_gateway_cfg(root, &temp_gw_cfg);
            break;
        case 3:
            add_slot_send_cfg(root, uc_static_get_slot_send_cfg());
            break;
        case 4:
            add_sync_cfg(root, uc_static_get_sync_cfg());
            break;
        default:
            is_have_data = RT_FALSE;
            get_cfg_cnt = 0;
            break;
        }

        if (is_have_data == RT_TRUE)
        {
            payload = cJSON_Print(root);
            get_cfg_cnt += 1;
        }

        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码 IoTE 状态
 *
 * @param  state IoTE 状态
 * @return 成功返回编码结果，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_iote_state(const void *state)
{
    char *payload = RT_NULL;
    mng_ul_iote_state_t *data = (mng_ul_iote_state_t *)state;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        // 编码 head 信息
        encode_head(root, &data->head);
        // 编码 IoTE 状态
        cJSON_AddStringToObject(root, "type", data->state.type);
        cJSON_AddStringToObject(root, "iote_ver", data->state.cur_version); // 与头的ver作区分
        cJSON_AddNumberToObject(root, "freq", data->state.freq);
        cJSON_AddNumberToObject(root, "rssi", ~(data->state.rssi - 1));
        cJSON_AddNumberToObject(root, "snr", data->state.snr);
        cJSON_AddNumberToObject(root, "cur_pow", data->state.cur_power);
        cJSON_AddNumberToObject(root, "min_pow", data->state.min_power);
        cJSON_AddNumberToObject(root, "max_pow", data->state.max_power);
        cJSON_AddNumberToObject(root, "cur_mcs", data->state.cur_mcs);
        cJSON_AddNumberToObject(root, "max_mcs", data->state.max_mcs);
        // 编码 JSON
        payload = cJSON_Print(root);
        // 释放 JSON
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码终端版本号查询响应
 *
 * @param  iote_ver IoTE版本
 * @return 成功返回编码结果，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_iote_version_response(const void *iote_ver)
{
    char *payload = RT_NULL;
    mng_ul_iote_version_t *data = (mng_ul_iote_version_t *)iote_ver;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        // 编码 head 信息
        encode_head(root, &data->head);
        // 编码 IoTE 状态
        cJSON_AddNumberToObject(root, "dev_id", data->iote_ver.dev_id);
        cJSON_AddStringToObject(root, "iote_ver", data->iote_ver.version); // 与头的ver作区分
        // 编码 JSON
        payload = cJSON_Print(root);
        // 释放 JSON
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码用户数据
 *
 * @param  user_data 用户数据
 * @return 成功返回编码结果，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_user_data(const void *user_data)
{
    // len > 310 * 4 / 3 + 4 = 417 AND len > 310 * 2 = 620
    char *payload = RT_NULL;

    mng_ul_userdata_t *data = (mng_ul_userdata_t *)user_data;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        // 编码 head 信息
        encode_head(root, &data->head);
        cJSON_AddStringToObject(root, "fmt", data->fmt);
        cJSON_AddStringToObject(root, "data", data->data);
        // 编码 JSON
        payload = cJSON_Print(root);
        // 释放 JSON
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

static void encode_get_cfg_head(cJSON *data_json)
{
    cJSON_AddNumberToObject(data_json, "cmd", PROT_QUERY_CONFIG);
    cJSON_AddStringToObject(data_json, "ver", PROT_VERSION);
    cJSON_AddNumberToObject(data_json, "src", 0);
    cJSON_AddNumberToObject(data_json, "dst", 0);
}

/**
 * @brief  编码 WIoTa 版本
 *
 * @param  ver WIoTa 版本
 * @return 成功返回编码结果，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_wiota_version(const void *ver)
{
    char *payload = RT_NULL;
    wiota_version_t *data = (wiota_version_t *)ver;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_wiota_version(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码 WIoTa 配置
 *
 * @param  cfg WIoTa 配置
 * @return 成功返回编码结果，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_wiota_sys_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    wiota_sys_cfg_t *data = (wiota_sys_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_wiota_sys_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码 WIoTa 连接态时间
 *
 * @param  cfg WIoTa 连接态时间
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_wiota_act_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    wiota_act_cfg_t *data = (wiota_act_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_wiota_act_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码 WIoTa 频点列表
 *
 * @param  cfg WIoTa 频点列表
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_wiota_freq_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    wiota_freq_cfg_t *data = (wiota_freq_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_wiota_freq_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码 WIoTa 发射功率
 *
 * @param  cfg WIoTa 发射功率
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_wiota_power_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    wiota_power_cfg_t *data = (wiota_power_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_wiota_power_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码 WIoTa 速率模式
 *
 * @param  cfg WIoTa 速率模式
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_wiota_rate_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    wiota_rate_cfg_t *data = (wiota_rate_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_wiota_rate_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码 WIoTa 连续信号唤醒配置
 *
 * @param  cfg WIoTa 连续信号唤醒配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_wiota_paging_tx_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    wiota_paging_tx_cfg_t *data = (wiota_paging_tx_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_wiota_paging_tx_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码 WIoTa 周期信号唤醒配置
 *
 * @param  cfg WIoTa 周期信号唤醒配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_wiota_sync_paging_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    wiota_sync_paging_cfg_t *data = (wiota_sync_paging_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_wiota_sync_paging_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码 WIoTa 授时配置
 *
 * @param  cfg WIoTa 授时配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_wiota_ts_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    wiota_ts_cfg_t *data = (wiota_ts_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_wiota_ts_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

#ifdef WIOTA_SUBF_MODE_SUPPORT
/**
 * @brief  编码 WIoTa 子帧模式配置
 *
 * @param  cfg WIoTa 子帧模式配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_wiota_subf_mode_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    wiota_subf_mode_cfg_t *data = (wiota_subf_mode_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_wiota_subf_mode_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}
#endif

/**
 * @brief  编码分时发送
 *
 * @param  cfg 分时发送
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_slot_send_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    slot_send_cfg_t *data = (slot_send_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_slot_send_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码uboot配置
 *
 * @param  cfg uboot配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_uboot_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    uboot_cfg_t *data = (uboot_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_uboot_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码立即生效配置
 *
 * @param  cfg 立即生效配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_immediate_effective_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    unsigned int *data = (unsigned int *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        cJSON_AddNumberToObject(root, IMMEDIATE_EFFECTIVE_CFG, data[0]);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码立即生效配置
 *
 * @param  cfg 立即生效配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_factory_test_result_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    factory_test_t *data = (factory_test_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    cJSON *factory = cJSON_CreateObject();

    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        for (int n = 0; n < MAX_TEST_PROJECT; n++)
        {
            add_test_cfg(root, &data[n]);
        }
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码网关基础配置
 *
 * @param  cfg 网关基础配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_gateway_base_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    gw_base_cfg_t *data = (gw_base_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_gateway_base_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码网关ID管理配置
 *
 * @param  cfg 网关ID管理配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_gateway_id_mng_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    gw_id_manager_cfg_t *data = (gw_id_manager_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_gateway_id_mng_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码鉴权信息
 *
 * @param  cfg 鉴权信息
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_gateway_auth_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    gw_auth_cfg_t *data = (gw_auth_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_gateway_auth_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码网络配置
 *
 * @param  cfg 网络配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_gateway_net_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    gw_net_cfg_t *data = (gw_net_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_gateway_net_policy_cfg(root, &data->net_policy_cfg);
        add_gateway_net_if_cfg(root, &data->net_if_cfg);
        add_gateway_wifi_cfg(root, &data->wifi_cfg);
        add_gateway_cat1_cfg(root, &data->cat1_cfg);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码网卡策略配置
 *
 * @param  cfg 网卡策略配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_gateway_net_policy_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    gw_net_policy_cfg_t *data = (gw_net_policy_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_gateway_net_policy_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码网口配置
 *
 * @param  cfg 网口配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_gateway_net_if_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    gw_net_if_cfg_t *data = (gw_net_if_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_gateway_net_if_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码 WIFI 配置
 *
 * @param  cfg WIFI 配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_gateway_wifi_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    gw_wifi_cfg_t *data = (gw_wifi_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_gateway_wifi_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码cat1配置
 *
 * @param  cfg cat1配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_gateway_cat1_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    gw_cat1_cfg_t *data = (gw_cat1_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_gateway_cat1_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码 蓝牙 配置
 *
 * @param  cfg 蓝牙 配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_gateway_bt_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    gw_bt_cfg_t *data = (gw_bt_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_gateway_bt_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码 MQTT 服务器
 *
 * @param  cfg MQTT 服务器
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_gateway_mqtt_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    gw_mqtt_server_cfg_t *data = (gw_mqtt_server_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_gateway_mqtt_server_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码上下行数据配置
 *
 * @param  cfg 上下行数据配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_gateway_data_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    gw_data_cfg_t *data = (gw_data_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_gateway_data_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码看门狗
 *
 * @param  cfg 看门狗
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_gateway_wtd_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    gw_wtd_cfg_t *data = (gw_wtd_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_gateway_wtd_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码LOG配置
 *
 * @param  cfg LOG配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_gateway_ftp_log_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    gw_ftp_log_cfg_t *data = (gw_ftp_log_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_gateway_ftp_log_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码LOG口切换配置
 *
 * @param  cfg LOG口切换配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_gateway_log_switch_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    gw_log_switch_cfg_t *data = (gw_log_switch_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_gateway_log_switch_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码uart_485配置
 *
 * @param  cfg uart_485配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_gateway_uart_485_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    gw_uart_485_cfg_t *data = (gw_uart_485_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_gateway_uart_485_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码网关定时配置
 *
 * @param  cfg 网关定时配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_gateway_timed_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    gw_timed_cfg_t *data = (gw_timed_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_gateway_timed_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码485透传数据
 *
 * @param  data 485透传数据
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_transparent_data(const void *transparent_data)
{
    char *payload = RT_NULL;
    net_dl_transparent_data_t *data = (net_dl_transparent_data_t *)transparent_data;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        // 编码 head 信息
        cJSON_AddNumberToObject(root, "cmd", data->cmd);
        cJSON_AddStringToObject(root, "ver", PROT_VERSION);
        cJSON_AddNumberToObject(root, "src", data->src_addr);
        cJSON_AddNumberToObject(root, "dst", data->dest_addr);
        cJSON_AddStringToObject(root, "fmt", data->fmt);
        cJSON_AddStringToObject(root, "data", data->transparent_data);
        // 编码 JSON
        payload = cJSON_Print(root);
        // 释放 JSON
        cJSON_Delete(root);
        root = RT_NULL;
    }

    rt_free(data->transparent_data);
    data->transparent_data = RT_NULL;

    return payload;
}

/**
 * @brief  编码设备状态
 *
 * @param  status 设备状态
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_device_status(const void *status)
{
    char *payload = RT_NULL;
    mng_ul_device_status_t *data = (mng_ul_device_status_t *)status;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        cJSON_AddNumberToObject(root, "cmd", data->cmd);
        cJSON_AddStringToObject(root, "ver", PROT_VERSION);
        cJSON_AddNumberToObject(root, "dev_id", data->dev_id);
        cJSON_AddNumberToObject(root, "status", data->status);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/** @brief  编码同步助手配置
 *
 * @param  cfg 同步助手配置
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_sync_cfg(const void *cfg)
{
    char *payload = RT_NULL;
    sync_cfg_t *data = (sync_cfg_t *)cfg;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        add_sync_cfg(root, data);
        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief 编码终端OTA升级完成消息
 *
 * @param cmp_info 升级完成消息
 * @return char* 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_ota_upgrade_complete_info(const void *cmp_info)
{
    char *payload = RT_NULL;
    ota_upgrade_complete_t *data = (ota_upgrade_complete_t *)cmp_info;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        cJSON_AddNumberToObject(root, "cmd", PROT_OTA_UPDATE_CMP);
        cJSON_AddStringToObject(root, "ver", PROT_VERSION);

        cJSON_AddStringToObject(root, "new_ver", data->new_version);
        cJSON_AddStringToObject(root, "old_ver", data->old_version);
        cJSON_AddStringToObject(root, "dev_type", data->device_type);
        cJSON_AddStringToObject(root, "note", data->note);

        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码鉴权列表信息
 *
 * @param  auth_info 鉴权列表信息
 * @param  is_over   发送完成标志
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_gateway_auth_list(const void *auth_info, int *is_over)
{
    char *payload = RT_NULL;
    gw_auth_list_info_t *data = (gw_auth_list_info_t *)auth_info;
    cJSON *root = cJSON_CreateObject();
    int total_num = 0;
    int left_num = 0;
    static int total_num_last = 0;

    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        if (data->auth_total_num == 0)
        {
            cJSON_AddNumberToObject(root, "auth_num", data->auth_total_num);
            *is_over = 1;
        }
        else
        {
            if (total_num_last < data->auth_total_num)
            {
                left_num = data->auth_total_num - total_num_last;
                if (left_num >= 30)
                {
                    total_num = 30;
                }
                else
                {
                    total_num = left_num;
                }
                cJSON_AddNumberToObject(root, "auth_num", total_num);
                for (int i = 0; i < total_num; i++)
                {
                    cJSON_AddStringToObject(root, data->auth_info[i + total_num_last].dev_id_key, data->auth_info[i + total_num_last].info_str);
                }

                total_num_last += total_num;
            }

            if (total_num_last >= data->auth_total_num)
            {
                total_num_last = 0;
                *is_over = 1;
                rt_free(data->auth_info);
            }
        }
        payload = cJSON_Print(root);

        cJSON_Delete(root);
        root = RT_NULL;
    }

    return payload;
}

/**
 * @brief  编码同步动态信息
 *
 * @param dynamics_info 同步动态信息
 * @return char*        成功返回编码对象，否则返回 RT_NULL
 */
char *encode_sync_dynamics_info(const void *dynamics_info)
{
    char *payload = RT_NULL;
    sync_dynamics_info_t *data = (sync_dynamics_info_t *)dynamics_info;
    cJSON *root = cJSON_CreateObject();
    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        cJSON_AddNumberToObject(root, "info_h", data->head);
        cJSON_AddNumberToObject(root, "my_id", data->my_id);
        cJSON_AddStringToObject(root, "sw", data->soft_version);
        cJSON_AddNumberToObject(root, "center_id", data->center_id);
        cJSON_AddNumberToObject(root, "nei_num", data->neighbor_num);
        cJSON *nei_obj = cJSON_CreateObject();
        for (int i = 0; i < data->neighbor_num; i++)
        {
            cJSON *nei_info = cJSON_CreateObject();
            char key[10] = {0};
            rt_snprintf(key, 10, "nei%d", i);
            cJSON_AddNumberToObject(nei_info, "dev_id", data->neighbor_info[i].dev_id);
            cJSON_AddNumberToObject(nei_info, SYMBOL_LENGTH, data->neighbor_info[i].symbol_len);
            cJSON_AddNumberToObject(nei_info, DLUL_RATIO, data->neighbor_info[i].ratio);
            cJSON_AddNumberToObject(nei_info, WIOTA_FREQ_CFG, data->neighbor_info[i].freq);
            cJSON_AddNumberToObject(nei_info, "center_id", data->neighbor_info[i].center_id);

            cJSON_AddItemToObject(nei_obj, key, nei_info);
        }
        cJSON_AddItemToObject(root, "nei_info", nei_obj);

        payload = cJSON_Print(root);
        cJSON_Delete(root);
        root = RT_NULL;
    }
    return payload;
}

/**
 * @brief  编码扫频响应信息
 *
 * @param  scan_resp 扫频响应信息
 * @param  is_over   发送完成标志
 * @return 成功返回编码对象，否则返回 RT_NULL
 * @note   编码结果需使用 rt_free 释放
 */
char *encode_gateway_scan_resp(const void *scan_resp, int *is_over)
{
    char *payload = RT_NULL;
    gw_scan_freq_resp_t *data = (gw_scan_freq_resp_t *)scan_resp;
    cJSON *root = cJSON_CreateObject();
    int res_num = 0;
    int left_num = 0;
    static int res_num_last = 0;

    if (RT_NULL != root && RT_NULL != data)
    {
        encode_get_cfg_head(root);
        cJSON_AddStringToObject(root, "result", data->result);
        cJSON_AddNumberToObject(root, "times", data->scaned_times);

        if (data->scan_res_num == 0)
        {
            cJSON_AddNumberToObject(root, "res_num", data->scan_res_num);
            *is_over = 1;
        }
        else
        {
            if (res_num_last < data->scan_res_num)
            {
                left_num = data->scan_res_num - res_num_last;
                if (left_num >= 30)
                {
                    res_num = 30;
                }
                else
                {
                    res_num = left_num;
                }
                cJSON_AddNumberToObject(root, "res_num", res_num);
                for (int i = 0; i < res_num; i++)
                {
                    cJSON_AddStringToObject(root, data->scan_res[i + res_num_last].freq_key, data->scan_res[i + res_num_last].info_str);
                }

                res_num_last += res_num;
            }

            if (res_num_last >= data->scan_res_num)
            {
                res_num_last = 0;
                *is_over = 1;
                rt_free(data->scan_res);
            }
        }
        payload = cJSON_Print(root);

        cJSON_Delete(root);
        root = RT_NULL;
    }

    return payload;
}